;#
;# syn_filt_asm.S
;#
;# Perform synthesis filtering through 1/A(z).
;# 
;# Oded Rosen, 2011   
;#

	.text
	.globl Syn_filt_inner
	
	.arm
	
;#************************************************************************
;#
;#  FUNCTION: Syn_filt 
;#
;#  PURPOSE: Perform synthesis filtering through 1/A(z)
;#
;#************************************************************************/

	;# inputs / outputs:
	a			.req r0 
	x			.req r1
	yy			.req r2
	lg			.req r3
		
	;# temp values:
	i			.req r4
	j			.req r5
	s			.req r6
	t1			.req r7
	t2			.req r8
	t3			.req r9
	jm			.req r10
	lg2			.req r11
	t4			.req r11

Syn_filt_inner:
		;# a[],		i   : a[M+1] prediction coefficients
		;# x[],		i   : input signal
		;# yy[],	o   : output signal
		;# lg,		i   : size of filtering

		;# Stack current values:
		PUSH		{r4-r11}							;# stack

		;# hold lg*2 in lg2 for loop comparison:
		ADD			lg2,lg,lg
		PUSH		{lg2}

		;# Outer loop pre:
		MOV			i,#0

sf_i_loop:
		;# s = L_mult (x[i], a[0])
		LDRSH		t1,[x,+i]
		LDRSH		t2,[a]
		SMULBB		s,t1,t2
		CMP			s,#0x40000000
		ADDNE		s,s,s
		BNE			sf_j_loop_pre
		MOV			s,#0x7fffffff

sf_j_loop_pre:
		;# Inner loop pre:
		MOV			j,#2
		MOV			jm,#-4

sf_j_loop:
		;# s = L_msu (s, a[j], yy[-j])
		LDR			t1,[a,+j]
		LDR			t2,[yy,jm]	
		SMULBT 		t3,t1,t2
		SMULTB 		t4,t1,t2 
		QDSUB		s,s,t3
		QDSUB		s,s,t4

sf_j_loop_post:
		ADD			j,j,#4
		ADD			jm,jm,#-4
		CMP			j,#22
		BLT			sf_j_loop
		
		;# s = L_shl (s, 3)
		CMP 		s,#0
		BEQ 		sf_round
		BMI			sf_neg
		CLZ 		t2,s
		CMP 		t2,#3
		MOVLE 		s,#0x7fffffff
		BLE			sf_round
		LSL 		s,s,#3		
		B			sf_round
sf_neg:
		NEG			s,s
		CLZ 		t2,s
		CMP 		t2,#3
		MOVLE 		s,#0x80000000
		BLE			sf_round
		LSL			s,s,#3
		NEG			s,s

sf_round:
		;# *yy = round (s);
		MOV 		t1,#0x00008000
		ADDS 		s,s,t1			
		LSRVC 		s,#16 
		BVC 		sf_i_loop_post 	
				
		MOVCS 		s,#0x80000000 
		MVNCC 		s,#0x80000000
		LSR 		s,#16  

sf_i_loop_post:
		STRH		s,[yy]
		; # Inner loop post:
		ADD			yy,yy,#2
		ADD			i,i,#2
		POP			{lg2}
		CMP			i,lg2
		PUSH		{lg2}
		BLT			sf_i_loop

		;# Unstack values and return:
		POP			{lg2}
		POP			{r4-r11}							;# unstack
		BX			lr									;# return
